<template>
    <div class="content">

        <el-tabs type="border-card" v-model="ns" @tab-click="handleNsChange">
            <el-tab-pane v-for="(item, index) in nss" :key="index" :label="item" :name="item" lazy>
                <!--  <span slot="label"><i class="el-icon-location"></i> {{item}}</span> -->
                <el-row>
                    <el-form :inline="true" class="demo-form-inline">
                        <el-form-item label="数据源" prop="ds">
                            <!--数据源-->
                            <el-select v-model="ds" placeholder="数据源" @change="handleDsChange">
                                <el-option v-for="(item,index) in dss" :key="index" :label="item.ds + ' | ' + item.dbName" :value="item.ds" />
                            </el-select>
                        </el-form-item>
                        <el-form-item label="模板">
                            <el-select v-model="templateId" placeholder="请选择代码模板" @change="handleTemplateChange">
                                <el-option v-for="(item, index) in templates" :key="index" :label="item.name" :value="item.id" />
                            </el-select>
                        </el-form-item>
                        <el-form-item label="表名">
                            <el-input v-model="tableName" placeholder="表名"></el-input>
                        </el-form-item>
                        <el-form-item>
                            <el-button type="primary" icon="el-icon-search" @click="handleQuery">查询</el-button>
                            <el-button type="primary" icon="el-icon-refresh-right" @click="handleClear">重置</el-button>
                            <el-button type="danger" icon="el-icon-delete" @click="handleGeneratorBatch()">批量代码生成</el-button>
                        </el-form-item>
                    </el-form>
                </el-row>
                <el-table ref="multipleTable" :data="pageData.list" border fit highlight-current-row :header-row-style="
              () => {
                return 'line-height:20px';
              }
            " :header-cell-style="{
              background: 'rgb(55, 60, 100)',
              color: '#FFFFFF',
              textAlign: 'center',
            }" :cell-style="{ textAlign: 'center' }" @selection-change="handleSelectionChange">
                    <el-table-column type="selection" width="40"> </el-table-column>
                    <el-table-column fixed prop="ds" label="数据源"></el-table-column>
                    <el-table-column fixed prop="schemaName" label="SCHEMA"></el-table-column>
                    <el-table-column fixed prop="tableName" label="表名"></el-table-column>
                    <el-table-column prop="engine" label="Engine" :show-overflow-tooltip="true">
                    </el-table-column>
                    <el-table-column prop="tableComment" label="表备注">
                    </el-table-column>
                    <el-table-column prop="createTime" label="创建时间">
                    </el-table-column>
                    <el-table-column fixed="right" label="操作" width="300">
                        <template slot-scope="scope">
                            <el-button type="text" size="small" icon="el-icon-view" @click="handlePreview(scope.row.tableName)">预览</el-button>
                            <el-button type="text" icon="el-icon-tickets" @click="handleQueryTableColumns(scope.row.tableName)" size="small">表字段</el-button>
                            <el-dialog :title="'表：' + tableColumnsData.tableName" :visible.sync="tableColumnsData.dialogVisible" width="50%" append-to-body>
                                <!--弹出的对话框的内容-->
                                <el-table ref="multipleTableColumns" :data="tableColumnsData.columns" border height="500" fit highlight-current-row :header-cell-style="{
                      background: 'rgb(55, 60, 100)',
                      color: ' #fff',
                      textAlign: 'center',
                    }" :cell-style="{ textAlign: 'center' }">
                                    <el-table-column prop="columnName" label="字段名称" width="150"></el-table-column>
                                    <el-table-column prop="dataType" label="数据类型" width="150"></el-table-column>
                                    <el-table-column prop="columnKey" label="索引" width="150"></el-table-column>
                                    <el-table-column prop="columnComment" label="字段描述" :show-overflow-tooltip="true">
                                    </el-table-column>
                                </el-table>
                            </el-dialog>
                        </template>
                    </el-table-column>
                </el-table>
                <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="pageData.currPage" :page-sizes="[10, 20, 50, 100]" :page-size="pageData.pageSize"
                    layout="total, sizes, prev, pager, next, jumper" :total="pageData.totalCount">
                </el-pagination>
                <!-- 预览界面 
                    <el-dialog :title="preview.title" :visible.sync="preview.open" width="80%" top="5vh" append-to-body class="scrollbar">
                        <el-tabs v-model="preview.activeName">
                            <el-tab-pane v-for="(value, key) in preview.data" :label="key" :name="key" :key="key">
                                <pre><code class="hljs">{{value}}</code></pre>
                            </el-tab-pane>
                        </el-tabs>
                    </el-dialog> -->

                <!-- 预览界面 -->
                <el-dialog :title="preview.title" :visible.sync="preview.open" width="95%" top="5vh" append-to-body class="scrollbar">
                    <el-row>
                        <el-col :span="5">
                            <el-tree :data="preview.fileTree" :expand-on-click-node="false" default-expand-all highlight-current @node-click="handleNodeClick" />
                        </el-col>
                        <el-col :span="19">
                            <el-tabs v-model="preview.activeName">
                                <el-tab-pane v-for="item in preview.data" :label="item.filePath.substring(item.filePath.lastIndexOf('/') + 1)" :name="item.filePath" :key="item.filePath">
                                    <el-link :underline="false" icon="el-icon-document-copy" v-clipboard:copy="item.code" v-clipboard:success="clipboardSuccess" style="float:right">复制</el-link>
                                    <pre><code class="hljs">{{item.code}}</code></pre>
                                </el-tab-pane>
                            </el-tabs>
                        </el-col>
                    </el-row>
                </el-dialog>
            </el-tab-pane>
        </el-tabs>

    </div>
</template>
<script>
    import { tablePage, tableColumns, previewTable, generatorCode } from '../../api/table'
    import { templateList } from '../../api/template'
    import { nsList } from '../../api/ns'
    import { dsList } from '../../api/ds';
    import { nsData } from '../../mixins/mixin'
    export default {
        created() {
            if (this.$route.query) {
                this.ns = this.$route.query.ns ? this.$route.query.ns : 'public'
                this.ds = this.$route.query.ds
            }
            this.getNsList()
            this.getDsList()
        },
        methods: {
            handleNsChange() {
                this.ds = ''
                this.dss = []
                this.handleDsChange()
            },
            handleDsChange() {
                this.templateId = null
                this.templates = []
                this.getDsList()
            },
            handleTemplateChange() {
                this.getTemplatesList()
            },
            handleGeneratorBatch() {
                if (this.multipleSelection.length === 0) {
                    this.$message({
                        type: 'info',
                        message: '请选择需要生成代码的数据表'
                    })
                } else {
                    const data = {
                        ns: this.ns,
                        ds: this.ds,
                        templateId: this.templateId,
                        tableNames: this.multipleSelection
                    }
                    generatorCode(data).then((res) => {
                        if (!res) {
                            return
                        }
                        const fileName = res.headers['content-disposition'].split('=')[1]
                        const blob = new Blob([res.data], {
                            type: 'application/zip;charset=UTF-8'
                        })
                        const url = window.URL.createObjectURL(blob)
                        const aLink = document.createElement('a')
                        aLink.style.display = 'none'
                        aLink.href = url
                        aLink.download = 'wtf.zip'
                        document.body.appendChild(aLink)
                        aLink.click()
                        document.body.removeChild(aLink)
                        window.URL.revokeObjectURL(url)
                    })
                }
            },
            handleQueryTableColumns(tableName) {
                this.tableColumnsData.dialogVisible = true
                this.tableColumnsData.tableName = tableName
                tableColumns(this.ns, this.ds, this.tableColumnsData.tableName).then(res => {
                    this.tableColumnsData.columns = res.data
                })
            },
            handleSelectionChange(selection) {
                this.multipleSelection = selection.map(item => item.tableName);
            },
            handleClear() {
                this.tableName = ''
                this.getPageList()
            },
            getDsList() {
                dsList(this.ns).then(res => {
                    this.dss = res.data
                    if (this.ds === null || this.ds === '' || this.ds === undefined) {
                        this.ds = this.dss.length === 0 ? '' : this.dss[0].ds
                    }
                }).then(res => {
                    this.getTemplatesList()
                })
            },
            getTemplatesList() {
                templateList(this.ns, this.ds).then((res) => {
                    this.templates = res.data;
                    this.templateId = this.templates.length > 0 ? this.templates[0].id : null
                }).then(res => {
                    this.getPageList()
                })
            },
            getPageList() {
                tablePage(this.ns, this.ds, this.tableName).then((res) => {
                    this.pageData = res.data

                })
            },
            handlePreview(tableName) {
                let tableNames = []
                tableNames.push(tableName)
                const data = {
                    ns: this.ns,
                    ds: this.ds,
                    templateId: this.templateId,
                    tableNames: tableNames
                }
                previewTable(data).then(res => {
                    this.preview.data = res.data;
                    this.preview.open = true;
                    let files = this.handleFiles(this.preview.data);
                    this.preview.fileTree = this.handleTree(files, "id", "parentId", "children", "/"); // "/" 为根节点
                    console.log("-1----->" + window.JSON.stringify(this.preview.fileTree, null, 4))
                });
            },
            handleTree(data, id, parentId, children, rootId) {
                id = id || 'id'
                parentId = parentId || 'parentId'
                children = children || 'children'
                rootId = rootId || Math.min.apply(Math, data.map(item => {
                    return item[parentId]
                })) || 0
                //对源数据深度克隆
                const cloneData = JSON.parse(JSON.stringify(data))
                //循环所有项
                const treeData = cloneData.filter(father => {
                    let branchArr = cloneData.filter(child => {
                        //返回每一项的子级数组
                        return father[id] === child[parentId]
                    });
                    branchArr.length > 0 ? father.children = branchArr : '';
                    //返回第一层
                    return father[parentId] === rootId;
                });
                return treeData !== '' ? treeData : data;
            },
            /** 生成 files 目录 **/
            handleFiles(datas) {
                let exists = {}; // key：file 的 id；value：true
                let files = [];
                // 遍历每个元素
                for (const data of datas) {
                    let paths = data.filePath.split('/');
                    let fullPath = ''; // 从头开始的路径，用于生成 id
                    // 特殊处理 java 文件
                    if (paths[paths.length - 1].indexOf('.java') >= 0) {
                        let newPaths = [];
                        for (let i = 0; i < paths.length; i++) {
                            let path = paths[i];
                            if (path !== 'java') {
                                newPaths.push(path);
                                continue;
                            }
                            newPaths.push(path);
                            // 特殊处理中间的 package，进行合并
                            let tmp = undefined;
                            while (i < paths.length) {
                                path = paths[i + 1];
                                if (path === 'controller'
                                    || path === 'convert'
                                    || path === 'dal'
                                    || path === 'enums'
                                    || path === 'service'
                                    || path === 'impl'
                                    || path === 'mapper'
                                    || path === 'entity'
                                    || path === 'generator'
                                    || path === 'vo' // 下面三个，主要是兜底。可能考虑到有人改了包结构
                                    || path === 'mysql'
                                    || path === 'dataobject') {
                                    break;
                                }
                                tmp = tmp ? tmp + '.' + path : path;
                                i++;
                            }
                            if (tmp) {
                                newPaths.push(tmp);
                            }
                        }
                        paths = newPaths;
                    }
                    // 遍历每个 path， 拼接成树
                    for (let i = 0; i < paths.length; i++) {
                        // 已经添加到 files 中，则跳过
                        let oldFullPath = fullPath;
                        // 下面的 replaceAll 的原因，是因为上面包处理了，导致和 tabs 不匹配，所以 replaceAll 下
                        fullPath = fullPath.length === 0 ? paths[i] : fullPath.replace('.', '/') + '/' + paths[i];
                        if (exists[fullPath]) {
                            continue;
                        }
                        // 添加到 files 中
                        exists[fullPath] = true;
                        files.push({
                            id: fullPath,
                            label: paths[i],
                            parentId: oldFullPath || '/'  // "/" 为根节点
                        });
                    }
                }
                console.log("------>" + window.JSON.stringify(files, null, 4))
                return files;
            },
            /** 节点单击事件 **/
            handleNodeClick(data, node) {
                if (node && !node.isLeaf) {
                    return false;
                }
                // 判断，如果非子节点，不允许选中
                this.preview.activeName = data.id;
            },
            /** 复制代码成功 */
            clipboardSuccess() {
                this.$modal.msgSuccess("复制成功");
            }
        },
        data() {
            return {
                templateId: null,
                dss: [],
                templates: [],
                tableColumnsData: {
                    dialogVisible: false,
                    tableName: '',
                    columns: []
                },
                loading: false,
                ds: '',
                tableName: '',
                // 预览参数
                preview: {
                    open: false,
                    title: "代码预览",
                    fileTree: [],
                    data: [],
                    activeName: "domain.java"
                }
            }
        },
        mixins: [nsData]
    }
</script>

<style scoped>
.content {
    margin: 20px 0px;
}
.el-table {
    margin: 20px 0px;
}
.el-row {
    margin-bottom: 20px;
    line-height: 10px;
}
.selection-button {
    margin-top: 20px;
    left: 0%;
}
</style>
